import treeUtils from "@/utils/treeUtils";
import {createDownloadFile, deepClone} from "@/utils/util";
import avueDataAdapter from "@/utils/avueDataAdapter";
import startSearchModel from "../config/startSearchModel";
import startCrudTools from "./startCrudTools";

function createMixin(option) {
    return {
        computed: {

            columns() {
                let temp = [];
                for (let i = 0; i < this.tableOption.column.length; i++) {
                    let column = this.tableOption.column[i];
                    if (!column.columnComponent) continue
                    temp.push(column);
                }
                return temp;
            },
            bindVal() {
                return {
                    ref: 'startTableCrud',
                    option: this.tableOption,
                    data: this.dataSource,
                    tableLoading: this.loading,
                    permission: this.getBtnPermission,
                    beforeOpen: this.dialogBeforeOpen,
                    beforeClose: this.dialogBeforeClose,
                    key: this.startTableCrudKey,
                    page: this.page
                }
            },
            onEvent() {
                return {
                    'on-load': this.loadListData,
                    'row-save': this.rowSave,
                    'row-update': this.rowUpdate,
                    'row-del': this.rowDel,
                    'refresh-change': this.refreshChange,
                    'search-reset': this.searchReRest,
                    'search-change': this.searchChange,
                    'selection-change': this.selectionChange,
                    'sort-change': this.sortChange
                }
            },
            rowKey() {
                return option.rowKey || 'id'
            }
        },
        data() {
            return {
                permissionBtn: {},
                tableOption: null,
                dataSource: [],
                startForm: {},
                searchParams: {},
                api: null,
                loading: false,
                page: {
                    currentPage: 1, pageSize: 10,
                },
                tempOption: null,
                columnsMap: {},
                selectList: [],
                startTableCrudKey: Math.random(),
            }
        },
        beforeCreate() {

        },
        created() {

        },
        methods: {

            /**
             * 初始化crud-crud 配置
             * @param crudOption avue 配置
             * @param api 访问的api
             */
            loadCrudOptionConfig(crudOption, api) {
                this.api = api;
                // console.log("option",crudOption)
                // console.log("api",api)
                if (this.loadCrudOptionBefore) {
                    this.loadCrudOptionBefore(crudOption)
                }
                let columns = crudOption.column;
                let columnsMap = {};
                for (let i = 0; i < columns.length; i++) {
                    let column = columns[i];
                    if (this.loadCrudColumnBefore) {
                        this.loadCrudColumnBefore(column)
                    }
                    if (column.search) {
                        columnsMap[column.prop] = column.searchModel ? column.searchModel : startSearchModel.EQ;
                    }
                }
                this.columnsMap = columnsMap;
                let permissionBtnTemp = crudOption.permissionBtn;
                if (!permissionBtnTemp) permissionBtnTemp = {};
                if (crudOption.permissionBtn) {
                    permissionBtnTemp = Object.assign(permissionBtnTemp, crudOption.permissionBtn)
                }
                if (this.loadCrudOptionAfter) {
                    this.loadCrudOptionAfter(crudOption)
                }
                this.permissionBtn = permissionBtnTemp
                this.tableOption = crudOption;
                // console.log("tableOption",crudOption)

            },
            loadRemoteDataSources() {
                // console.log("searchParams", this.searchParams)
                this.loading = true;
                this.dataSource = [];
                let pageParams = {}

                pageParams[option.current || 'current'] = this.page.currentPage
                pageParams[option.size || 'size'] = this.page.pageSize;
                let searchParams = startCrudTools.getSearchParams(this.searchParams, this.columnsMap);
                if (this.beforeLoadDataSource) {
                    let tempSearchParams = this.beforeLoadDataSource(searchParams)
                    searchParams = tempSearchParams ? tempSearchParams : searchParams;
                }
                const requestData = Object.assign({}, pageParams, this.searchParams, searchParams)

                let listApiName = option.list ? option.list : 'list';
                // console.log(this.api)
                let listApi = this.api[listApiName]
                if (!listApi) {
                    this.loading = false
                    this.$message.error("未配置list查询接口，请先配置查询接口")
                    return
                }
                listApi(requestData).then(res => {
                    let data = res.data.data;
                    if (this.afterLoadDataSource) {
                        this.afterLoadDataSource(data)
                    }
                    let tempDataList;
                    if (data instanceof Array) {
                        tempDataList = data;
                    } else {
                        tempDataList = data[option.data || 'records'];
                        this.page.total = data[option.total || 'total'];
                    }
                    avueDataAdapter.transformDataList(this.tableOption.column, tempDataList)
                    if (option.isTreeData) {
                        tempDataList = treeUtils.listToTree(tempDataList)
                    }
                    if (this.beforeRenderDataSource) {
                        this.beforeRenderDataSource(tempDataList)
                    }
                    this.dataSource = tempDataList;
                    if (!this.afterRenderDataSource) {
                        return
                    }
                    this.$nextTick(() => {
                        this.afterRenderDataSource(data)
                    })
                }).finally(() => this.loading = false)

            },
            restLoadList() {
                this.page.currentPage = 1;
                this.loadRemoteDataSources()
            },
            rowSave(row, done, loading) {
                delete this.startForm.params;
                if (this.rowSaveBefore) {
                    let tempRow = this.rowSaveBefore(row);
                    if (tempRow) {
                        row = tempRow
                    }
                }
                avueDataAdapter.transformDataSave(this.tableOption.column, row)
                let addApi = this.api[option.add || 'add']
                if (!addApi) {
                    this.$message.error("未配置add查询接口，请先配置查询接口")
                    return
                }
                addApi(row).then((data) => {
                    this.loadRemoteDataSources()
                    this.$message.success('新增成功')
                    if (this.afterRowSave) this.afterRowSave(row, data);
                    done();
                }).finally(() => {
                    loading()
                })
            },
            rowUpdate(row, index, done, loading) {
                // console.log("update", row)
                delete this.startForm.params;
                if (this.beforeRowUpdate) {
                    let tempRow = this.beforeRowUpdate(row, index);
                    if (tempRow) {
                        row = tempRow
                    }
                }
                avueDataAdapter.transformDataSave(this.tableOption.column, row)
                let updateApi = this.api[option.update || 'updateById'];
                if (!updateApi) {
                    this.$message.error("未配置update接口，请先配置修改接口")
                    return
                }
                updateApi(row).then((data) => {
                    this.loadRemoteDataSources()
                    this.$message.success('更新成功')
                    if (this.afterRowUpdate) this.afterRowUpdate(row, index);
                    done()
                }).finally(() => {
                    loading()
                })

            },
            rowDel(row, index) {
                let deleteApi = this.api[option.delete || 'deleteById']
                if (!deleteApi) {
                    this.$message.error("未配置delete查询接口，请先配置查询接口")
                    return
                }

                this.$confirm(`此操作将永久删除序号为【${index + 1}】的数据！ 是否继续?`, '系统提示', {
                    confirmButtonText: '是', cancelButtonText: '否', type: 'warning'
                }).then(() => {
                    if (this.beforeRowDel) this.beforeRowDel(row, index);
                    return deleteApi(row[this.rowKey], row)
                }).then(res => {
                    this.loadRemoteDataSources()
                    this.$message.success('删除成功')
                    if (this.rowDelAfter) this.rowDelAfter(row, index);
                }).catch(e => {

                })

            },
            batchRowDel() {
                let batchDeleteApi = this.api[option.deletes || 'deleteByIds']
                if (!batchDeleteApi) {
                    this.$message.error("未配置deletes查询接口，请先配置查询接口")
                    return
                }

                if (this.selectList.length < 1) return;
                let selectList = deepClone(this.selectList);
                let ids = selectList.map(item => item[this.rowKey]).filter(key => !!key);
                if (!ids) {
                    return;
                }
                this.$confirm(`此操作将永久删除id为【${ids.join('\n')}】的数据！ 是否继续?`, '系统提示', {
                    confirmButtonText: '是', cancelButtonText: '否', type: 'warning'
                }).then(() => {
                    if (this.beforeBatchRowDel) {
                        this.beforeBatchRowDel(ids, selectList)
                    }
                    return batchDeleteApi(ids)
                }).then(() => {
                    this.loadRemoteDataSources()
                    this.$message.success('删除成功')
                    if (this.afterBatchRowDel) {
                        this.afterBatchRowDel(ids, selectList)
                    }
                })

            },
            searchReRest(params, done) {
                if (this.searchReRestBefore) {
                    this.searchReRestBefore(params, done)
                }
                this.searchChange(params, done)
            },
            searchChange(params, done) {
                if (done) done();
                this.page.currentPage = 1;
                this.searchParams = params;
                this.loadRemoteDataSources()
            },
            loadListData(page) {
                this.page = page;
                this.loadRemoteDataSources()
            },
            refreshChange() {
                this.loadRemoteDataSources()
            },
            getBtnPermission(btnKey, row, index, defaultValue = true) {
                return startCrudTools.hasBtnPermission(this, option, btnKey, row, index, defaultValue)
            },
            downloadTemplate(fileName) {
                let downloadTemplate = this.api[option.downloadTemplate || 'downloadTemplate'];
                if (!downloadTemplate) {
                    this.$message.info("未定义模板下载接口")
                    return
                }
                downloadTemplate().then(res => createDownloadFile(res, fileName))
            },
            downloadExportExcel(fileName) {

                let exportExcelApi = this.api[option.exportExcel || 'exportExcel'];
                if (!exportExcelApi) {
                    this.$message.error("未配置exportExcel查询接口，请先配置查询接口")
                    return
                }
                if (!exportExcel) {
                    this.$message.info("未定义数据导出接口")
                    return;
                }
                let searchParams = startCrudTools.getSearchParams(this.searchParams, this.columnsMap);
                exportExcel(searchParams).then(res => createDownloadFile(res, fileName));
            },
            handlerImportExcel() {
                let importExcelApi = this.api[option.importExcel || 'importExcel'];
                if (!importExcelApi) {
                    this.$message.info("未定义数据导入接口")
                    return
                }
                this.$refs.importExcel.show();
            },
            selectionChange(list) {
                this.selectList = list;
            },

            sortChange(val) {
                // console.log("排序变化", val)
            },
            dialogBeforeOpen(show, type) {
                let handler = null;
                let customHandler = false;
                if (type === 'add' && this.beforeOpenAddDialog) {
                    customHandler = true;
                    handler = this.beforeOpenAddDialog(this.startForm, show)
                } else if (type === 'edit' && this.beforeOpenEditDialog) {
                    customHandler = true;
                    handler = this.beforeOpenEditDialog(this.startForm, show)
                } else if (type === "view" && this.beforeOpenViewDialog) {
                    customHandler = true;
                    handler = this.beforeOpenViewDialog(this.startForm, show)
                }
                if (!customHandler) {
                    show()
                }
            },
            dialogBeforeClose(done, type) {
                let handler = null;
                if (type === 'add' && this.beforeCloseAddDialog) {
                    handler = this.beforeCloseAddDialog(this.startForm, done)
                } else if (type === 'edit' && this.beforeCloseEditDialog) {
                    handler = this.beforeCloseEditDialog(this.startForm, done)
                } else if (type === "view" && this.beforeCloseViewDialog) {
                    handler = this.beforeCloseViewDialog(this.startForm, done)
                }
                if (!handler) {
                    done()
                }
            },
        },
    }

}

const startBaseCrud = {}
startBaseCrud.createMixin = createMixin
export default startBaseCrud
